#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <vector>
#include <thread>
#include <sstream>

#include <string.h>
#include <time.h>

#include <windows.h>
#include <psapi.h>
#pragma comment(lib,"psapi.lib")

using namespace std;

const int buffersize = 4096;

bool GetFileWords(const char* filename, vector<std::string>& words) 
{
    const auto delims = " \t\r\n\f,.\"\'()[]{}!:;&";
    
    std::fstream fs;
    fs.open(filename, std::fstream::in);
    if(!fs.good()) {
        cerr << ">> fstream open file error" << endl;
        return false;
    }
    char buffer[buffersize];

    char* saveptr = nullptr;
    while (fs.getline(buffer, sizeof(buffer) - 1).good()) {
        auto token = strtok_r(buffer, delims, &saveptr);
        while (token != nullptr) {
            words.emplace_back(token);
            token = strtok_r(nullptr, delims, &saveptr);
        }
    }
    
    fs.close();
    return true;
}

bool GetAccessSequence(const char* filename, vector<int>& seqs) {
    std::fstream fs;
    fs.open(filename, std::fstream::in);
    if(!fs.good()) {
        cerr << ">> fstream open file error" << endl;
        return false;
    }
    char buf[100];
    int seq;
    while(fs.getline(buf, sizeof(buf) - 1).good()) {
        seq = atoi(buf);
        seqs.emplace_back(seq);
    }
    return true;
}

void testAddString(string strvec[], string filename)
{
    vector<std::string> words;
    GetFileWords(filename.c_str(), words);
    std::cout << "words.size() = " << words.size() << std::endl;

    clock_t t1 = clock();

    for(int i = 0; i < words.size(); ++i) {
        strvec[i] = words[i];
    }
    clock_t t2 = clock();
    std::cout << "SaveStringTime_used: " << (t2 - t1) / (CLOCKS_PER_SEC / 1000) << " millisecond(s)" << std::endl;
}

void testGetString(string strvec[])
{
    vector<int> seqs;
    GetAccessSequence("TestFiles/testseq/test_seq_1000000.txt", seqs);
    clock_t t3 = clock();
    for(auto seq : seqs) {
        // string str = strvec[seq];
        strvec[seq];
    }
    clock_t t4 = clock();
    std::cout << "GetStringTime_used: " << (t4 - t3) / (CLOCKS_PER_SEC / 1000) << " millisecond(s)" << std::endl;
}

void testMemUsed()
{
    HANDLE handle = GetCurrentProcess();
    PROCESS_MEMORY_COUNTERS pmc;
    GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));

    std::cout << "Memery_used: " << pmc.WorkingSetSize/(1024*1024) - 3 << " MB" << std::endl;  //结果单位是Byte，3MB是公共开销，通过helloworld程序测试得
}

void testDelString(string strvec[])
{
    clock_t t5 = clock();
    // for(int i = 0; i < 100000; ++i) {
    //     strvec[i].~string();
    // }
    delete[] strvec;
    strvec = nullptr;
    clock_t t6 = clock();
    std::cout << "DelStringTime_used: " << (t6 - t5) / (CLOCKS_PER_SEC / 1000) << " millisecond(s)" << std::endl;
}

void test(string filename)
{
    cout << "Test started" << endl;
    cout << filename << endl;
    string* strvec = new string[1000000];
    testAddString(strvec, filename);
    testGetString(strvec);
    testMemUsed();
    testDelString(strvec);
    // delete strvec;
    // strvec = nullptr;
    cout << endl;
}

int main()
{
    int byte[] = {8};//, 16, 32, 64, 128};
    for(int a : byte) {
        string file = "TestFiles/finaltest/test_emulated_50%_1000w_" + to_string(a) + ".txt";
        test(file);
    }
    
    system("pause");
}